﻿using BootstrapBlazor.Components;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.SignalR.Client;
using System;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using System.Xml.Linq;
using TrackSystem.IO.Formula;
using TrackSystem.IO.Loops;
using static System.Net.Mime.MediaTypeNames;

namespace TrackSystem.UI.Server.Units
{
    public partial class LoopView
    {
        [Parameter]
        public required LoopItem loop { get; set; }

        [Parameter]
        public required HubConnection hub { get; set; }

        [Inject]
        [NotNull]
        private DialogService? DialogService { get; set; }

        private Chart _svpvChart = default!;
        private Chart _opChart = default!;
        private readonly List<double> _lstSV = [];
        private readonly List<double> _lstPV = [];
        private readonly List<double> _lstOP = [];
        private int _pvIndex = 0;
        private int _opIndex = 0;

        /// <summary>
        /// 初始化曲线
        /// </summary>
        /// <returns></returns>
        private async Task<ChartDataSource> OnInitContinue1()
        {
            var ds = new ChartDataSource();
            ds.Options.LegendLabelsFontSize = 12;

            _pvIndex++;
            if (_lstSV.Count > 40) _lstSV.RemoveAt(0);
            _lstSV.Add(loop.SV);
            if (_lstPV.Count > 40) _lstPV.RemoveAt(0);
            _lstPV.Add(loop.PV);

            ds.Labels = Enumerable.Range(_pvIndex, 40).Select(i => i.ToString());
            ds.Data.Add(new ChartDataset()
            {
                BorderWidth = 1,
                Label = $"设定: {loop.SVName}",
                Data = _lstSV.Select(i => (object)i),
                ShowPointStyle = false,
                PointStyle = ChartPointStyle.Circle,
                PointRadius = 2,
                PointHoverRadius = 4
            });
            ds.Data.Add(new ChartDataset()
            {
                BorderWidth = 1,
                Label = $"实际: {loop.PVName}",
                Data = _lstPV.Select(i => (object)i),
                ShowPointStyle = false,
                PointStyle = ChartPointStyle.Circle,
                PointRadius = 2,
                PointHoverRadius = 4
            });

            await Task.Delay(100);
            return ds;
        }

        private async Task<ChartDataSource> OnInitContinue2()
        {
            var ds = new ChartDataSource();
            ds.Options.LegendLabelsFontSize = 12;

            _opIndex++;
            if (_lstOP.Count > 40) _lstOP.RemoveAt(0);
            _lstOP.Add(loop.OP);

            ds.Labels = Enumerable.Range(_opIndex, 40).Select(i => i.ToString());
            ds.Data.Add(new ChartDataset()
            {
                BorderWidth = 1,
                Label = $"输出: {loop.OPName}",
                Data = _lstOP.Select(i => (object)i),
                ShowPointStyle = false,
                PointStyle = ChartPointStyle.Circle,
                PointRadius = 2,
                PointHoverRadius = 4
            });

            await Task.Delay(100);
            return ds;
        }


        private readonly CancellationTokenSource _cancellationTokenSource = new();
        /// <summary>
        /// <inheritdoc/>
        /// </summary>
        /// <param name="firstRender"></param>
        protected override void OnAfterRender(bool firstRender)
        {
            base.OnAfterRender(firstRender);

            if (firstRender)
            {
                Task.Run(async () =>
                {
                    while (!_cancellationTokenSource.IsCancellationRequested)
                    {
                        try
                        {
                            await Task.Delay(1000, _cancellationTokenSource.Token);

                            if (loop.Enabled)
                            {
                                await _svpvChart.Reload();
                                await _opChart.Reload();
                            }
                        }
                        catch (OperationCanceledException) { }
                    }

                });
            }
        }

        /// <summary>
        /// <inheritdoc/>
        /// </summary>
        /// <exception cref="NotImplementedException"></exception>
        public void Dispose()
        {
            _cancellationTokenSource.Cancel();
            _cancellationTokenSource.Dispose();
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 修改值
        /// </summary>
        /// <param name="name"></param>
        /// <param name="flag"></param>
        /// <returns></returns>
        private async Task SetValue(string name, bool flag)
        {
            try
            {
                if (hub.State == HubConnectionState.Connected)
                    await hub.SendAsync("Assign", name, new OperandDef(flag));
            }
            catch (Exception _)
            {
                // ignored
            }
        }

        /// <summary>
        /// 修改变量值
        /// </summary>
        /// <param name="regName"></param>
        /// <param name="regValue"></param>
        /// <returns></returns>
        private async Task ChangValueInt(string regName, double regValue)
        {
            var data = new FooInt { val = (int)regValue };

            var option = new EditDialogOption<FooInt>()
            {
                Title = regName,
                Model = data,
                RowType = RowType.Inline,
                ShowLoading = true,
                ItemsPerRow = 1,
                ItemChangedType = ItemChangedType.Update,
                OnEditAsync = async context =>
                {
                    await hub.SendAsync("Assign", regName, new OperandDef(data.val));
                    return true;
                }
            };
            await DialogService.ShowEditDialog(option);
        }

        /// <summary>
        /// 修改变量值
        /// </summary>
        /// <param name="regName"></param>
        /// <param name="regValue"></param>
        /// <returns></returns>
        private async Task ChangValueDouble(string regName, double regValue)
        {
            var data = new FooDouble { val = regValue };

            var option = new EditDialogOption<FooDouble>()
            {
                Title = regName,
                Model = data,
                RowType = RowType.Inline,
                ShowLoading = true,
                ItemsPerRow = 1,
                ItemChangedType = ItemChangedType.Update,
                OnEditAsync = async context =>
                {
                    await hub.SendAsync("Assign", regName, new OperandDef(data.val));
                    return true;
                }
            };
            await DialogService.ShowEditDialog(option);
        }

        /// <summary>
        /// 保存数据到数据表中
        /// </summary>
        /// <returns></returns>
        private async Task DataSaveToTable()
        {
            try
            {
                if (hub.State == HubConnectionState.Connected)
                    await hub.SendAsync("DataSaveToTable", loop.Name);
            }
            catch (Exception _)
            {
                // ignored
            }
        }

        /// <summary>
        /// 修改先进功能变量
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        private async Task OnAdvancedChanged(int val)
        {
            try
            {
                if (hub.State == HubConnectionState.Connected)
                    await hub.SendAsync("Assign", loop.Name + "_EnabledAd", new OperandDef(val));
            }
            catch (Exception _)
            {
                // ignored
            }
        }

        /// <summary>
        /// 自整定功能变量
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        private async Task OnAutoTunedChanged(int val)
        {
            try
            {
                if (hub.State == HubConnectionState.Connected)
                    await hub.SendAsync("Assign", loop.Name + "_AutoTuned", new OperandDef(val));
            }
            catch (Exception _)
            {
                // ignored
            }
        }

        /// <summary>
        /// 清除曲线数据
        /// </summary>
        /// <returns></returns>
        private Task OnClearData()
        {
            _lstSV.Clear();
            _lstOP.Clear();
            _lstPV.Clear();
            return Task.CompletedTask;
        }
    }

    class FooDouble
    {
        [Display(Name = "浮点数变量")]
        public double val { get; set; }
    }

    class FooInt
    {
        [Display(Name = "整型变量")]
        public int val { get; set; }
    }
}
